﻿using HybridCLR;
//using HybridCLR.Editor;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.AddressableAssets.ResourceLocators;
using UnityEngine.ResourceManagement.AsyncOperations;

public class CheckUpdate : MonoBehaviour
{
    private List<string> MetadataList = new List<string>()
    {
         "mscorlib.dll",
         "System.Core.dll",
         "System.dll",
    };

    [Serializable]
    private class DownloadInfo
    {
        public List<string> CatalogsInfo = new List<string>();
    }

    private DownloadInfo m_DownloadInfo = new DownloadInfo();

    private List<object> DownloadCatalogsKey = new List<object>();

    private string DOWNLOADKEY = "DOWNLOADKEY";

    private bool HasCatalogsUpdate => m_DownloadInfo != null && m_DownloadInfo.CatalogsInfo != null && m_DownloadInfo.CatalogsInfo.Count > 0;


    // Start is called before the first frame update
    void Start()
    {
        #region 注释
        // Addressables.CheckForCatalogUpdates();
        // 检查目录更新
        // Addressables.UpdateCatalogs();
        // 更新目录 把要更新的目录保存
        //服务器更新
        //本地保存目录的更新
        //IResourceLocator locator;
        //下载对应资源文件
        // 下载完成之后  再把保存的数据删除掉
        // Addressables.DownloadDependenciesAsync();
        #endregion

        DontDestroyOnLoad(this);

        StartCoroutine(Check());
    }


    private IEnumerator Check()
    {
        //补充元数据
        yield return LoadMetadata();
        //检查资源更新
        yield return CheckAssetUpdate();
        //下载资源
        yield return DownloadAsset();
        //加载热更新程序集
        yield return LoadHotUpdateAssembly();
        //加载热更新的场景
        yield return LoadScene("EntryScene");
        //加载热更新的场景
        yield return LoadScene("GameScene");
        //生成player
        yield return LoadPlayer();

    }

    private IEnumerator LoadMetadata()
    {
        foreach (var str in MetadataList)
        {

            var handle = Addressables.LoadAssetAsync<TextAsset>(str);

            byte[] metadate = handle.WaitForCompletion().bytes;

            LoadImageErrorCode err = RuntimeApi.LoadMetadataForAOTAssembly(metadate, HomologousImageMode.SuperSet);
            Debug.Log(err);
        }

        yield return null;
    }

    private IEnumerator CheckAssetUpdate()
    {
        AsyncOperationHandle<List<string>> CatalogsHandle = Addressables.CheckForCatalogUpdates(false);

        yield return CatalogsHandle;

        if (CatalogsHandle.Status == AsyncOperationStatus.Succeeded)
        {
            Debug.Log("检查目录更新成功");

            m_DownloadInfo.CatalogsInfo = CatalogsHandle.Result;

            Addressables.Release(CatalogsHandle);

            if (HasCatalogsUpdate)
            {
                //服务器有更新
                //保存 更新的数据
                Debug.Log("服务器有资源更新");
                string JsonStr = JsonUtility.ToJson(m_DownloadInfo);
                PlayerPrefs.SetString(DOWNLOADKEY, JsonStr);

            }
            else
            {
                //服务器没有更新
                //检查上次更新 保存的数据 
                if (PlayerPrefs.HasKey(DOWNLOADKEY))
                {
                    Debug.Log("服务器有未完成更新的资源");

                    string Str = PlayerPrefs.GetString(DOWNLOADKEY);

                    JsonUtility.FromJsonOverwrite(Str, m_DownloadInfo);
                }
            }

            if (HasCatalogsUpdate)
            {
                //更新目录

                AsyncOperationHandle<List<IResourceLocator>> LocatorHandle = Addressables.UpdateCatalogs(m_DownloadInfo.CatalogsInfo, false);

                yield return LocatorHandle;

                if (LocatorHandle.Status == AsyncOperationStatus.Succeeded)
                {
                    Debug.Log("更新目录成功");

                    List<IResourceLocator> resourceLocators = LocatorHandle.Result;

                    Addressables.Release(LocatorHandle);

                    DownloadCatalogsKey.Clear();

                    foreach (IResourceLocator locator in resourceLocators)
                    {
                        DownloadCatalogsKey.AddRange(locator.Keys);
                    }
                }
                else
                {
                    Debug.Log("更新目录失败");
                }
            }
        }
        else
        {
            Debug.Log("检查目录更新失败");

        }


    }

    private IEnumerator DownloadAsset()
    {
        AsyncOperationHandle<long> SizeHandle = Addressables.GetDownloadSizeAsync((IEnumerable)DownloadCatalogsKey);

        yield return SizeHandle;

        long Size = SizeHandle.Result;

        if (Size == 0) yield break;

        Debug.Log("资源需要下载");

        AsyncOperationHandle Handle = Addressables.DownloadDependenciesAsync((IEnumerable)DownloadCatalogsKey, Addressables.MergeMode.Union, false);

        yield return Handle;

        if (Handle.Status == AsyncOperationStatus.Succeeded)
        {
            PlayerPrefs.DeleteKey(DOWNLOADKEY);
            Debug.Log("下载完成");
        }
        else Debug.Log("下载失败");

        Addressables.Release(Handle);
    }

    private IEnumerator LoadHotUpdateAssembly()
    {

        string Label = "Assembly";

        AsyncOperationHandle<IList<TextAsset>> asshandle = Addressables.LoadAssetsAsync<TextAsset>(Label, null);

        IList<TextAsset> dllList = asshandle.WaitForCompletion();

        foreach (TextAsset dll in dllList)
        {
            byte[] ass = dll.bytes;
            Assembly.Load(ass);
        }


        yield return null;
    }

    private IEnumerator LoadScene(string SceneName)
    {
        yield return new WaitForSeconds(1);

        var Handle = Addressables.LoadSceneAsync(SceneName);

        yield return Handle;

        if (Handle.Status == AsyncOperationStatus.Failed)
        {
            Debug.Log("场景加载失败");
            yield break;
        }

        Debug.Log("场景加载成功");
        yield return new WaitForSeconds(1);

    }

    private IEnumerator LoadPlayer()
    {
        var handle =  Addressables.LoadAssetAsync<GameObject>("Player");

        GameObject player = handle.WaitForCompletion();

        yield return new WaitForSeconds(0.5f);
        Instantiate(player);

    }



    //private IEnumerator LoadCube()
    //{
    //    AsyncOperationHandle<TextAsset> Handle = Addressables.LoadAssetAsync<TextAsset>("HotUpdate.dll");

    //    Handle.WaitForCompletion();

    //    var Dll = Handle.Result;

    //    Assembly.Load(Dll.bytes);

    //    AsyncOperationHandle<GameObject> ObjHandle = Addressables.LoadAssetAsync<GameObject>("Cube");

    //    yield return ObjHandle;

    //    if (ObjHandle.Status == AsyncOperationStatus.Succeeded)
    //    {
    //        GameObject obj = ObjHandle.Result;
    //        Instantiate(obj);
    //        Debug.Log("Cube生成成功");
    //    }
    //    else
    //    {
    //        Debug.Log("Cube生成成功");
    //    }
    //    Addressables.Release(ObjHandle);
    //}

    //private IEnumerator CheckAssetUpdate()
    //{
    //    AsyncOperationHandle<List<string>> CatalogsHandle = Addressables.CheckForCatalogUpdates(false);

    //    yield return CatalogsHandle;

    //    if (CatalogsHandle.Status == AsyncOperationStatus.Succeeded)
    //    {
    //        // 检查目录更新成功
    //        Debug.Log("检查目录更新成功");

    //        List<string> Catalogs = CatalogsHandle.Result;

    //        Addressables.Release(CatalogsHandle);

    //        if (Catalogs.Count > 0)
    //        {
    //            //有资源更新
    //            Debug.Log("服务器有资源更新");
    //            AsyncOperationHandle<List<IResourceLocator>> LocatorHandle = Addressables.UpdateCatalogs(Catalogs, false);

    //            yield return LocatorHandle;

    //            if (LocatorHandle.Status == AsyncOperationStatus.Succeeded)
    //            {
    //                //更新目录成功
    //                Debug.Log("更新目录成功");

    //                List<IResourceLocator> resourceLocators = LocatorHandle.Result;

    //                Addressables.Release(LocatorHandle);

    //                DownloadCatalogsKey.Clear();

    //                foreach (IResourceLocator locator in resourceLocators)
    //                {
    //                    DownloadCatalogsKey.AddRange(locator.Keys);
    //                }

    //            }
    //            else
    //            {
    //                //更新目录失败
    //                Debug.Log("更新目录失败");
    //            }

    //        }
    //        else
    //        {
    //            //没有资源更新
    //            Debug.Log("服务器没有资源更新");

    //        }
    //    }
    //    else
    //    {
    //        // 检查目录更新失败
    //        Debug.Log("检查目录更新失败");
    //    }
    //}
}